package com.meteor.user.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fhs.trans.service.impl.DictionaryTransService;
import com.meteor.framework.common.enums.UserAdminEnum;
import com.meteor.framework.security.user.SecurityUser;
import com.meteor.user.entity.SysDictData;
import lombok.AllArgsConstructor;
import com.meteor.framework.common.exception.ServerException;
import com.meteor.framework.common.utils.PageResult;
import com.meteor.framework.mybatis.service.impl.BaseServiceImpl;
import com.meteor.user.convert.SysDictTypeConvert;
import com.meteor.user.mapper.SysDictDataMapper;
import com.meteor.user.mapper.SysDictTypeMapper;
import com.meteor.user.entity.SysDictType;
import com.meteor.user.enums.DictSourceEnum;
import com.meteor.user.query.SysDictTypeQuery;
import com.meteor.user.service.SysDictTypeService;
import com.meteor.user.vo.SysDictTypeVO;
import com.meteor.user.vo.SysDictVO;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 字典类型
 *
 * @author lynn
 * @date 2024/1/03
 */
@Service
@AllArgsConstructor
public class SysDictTypeServiceImpl extends BaseServiceImpl<SysDictTypeMapper, SysDictType> implements SysDictTypeService, InitializingBean {
    private final SysDictDataMapper sysDictDataMapper;
    private final DictionaryTransService dictionaryTransService;

    @Override
    public PageResult<SysDictTypeVO> page(SysDictTypeQuery query) {
        IPage<SysDictType> page = baseMapper.selectPage(getPage(query), getWrapper(query));
        return new PageResult<>(SysDictTypeConvert.INSTANCE.convertList(page.getRecords()), page.getTotal());
    }

    private Wrapper<SysDictType> getWrapper(SysDictTypeQuery query) {
        LambdaQueryWrapper<SysDictType> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StrUtil.isNotBlank(query.getDictType()), SysDictType::getDictType, query.getDictType());
        wrapper.like(StrUtil.isNotBlank(query.getDictName()), SysDictType::getDictName, query.getDictName());
        wrapper.orderByAsc(SysDictType::getSort);

        return wrapper;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(SysDictTypeVO vo) {
        SysDictType entity = SysDictTypeConvert.INSTANCE.convert(vo);

        baseMapper.insert(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SysDictTypeVO vo) {
        SysDictType entity = SysDictTypeConvert.INSTANCE.convert(vo);

        updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<String> idList) {
        removeByIds(idList);
    }

    @Override
    public List<SysDictVO.DictData> getDictSql(String id) {
        SysDictType entity = this.getById(id);
        try {
            return sysDictDataMapper.getListForSql(entity.getDictSql());
        } catch (Exception e) {
            throw new ServerException("动态SQL执行失败，请检查SQL是否正确！");
        }
    }

    @Override
    public List<SysDictVO> getDictList() {
        // 全部字典类型列表
        List<SysDictType> typeList = this.list(Wrappers.emptyWrapper());

        // 全部字典数据列表
        QueryWrapper<SysDictData> query = new QueryWrapper<SysDictData>().orderByAsc("sort");
        List<SysDictData> dataList = sysDictDataMapper.selectList(query);

        // 全部字典列表
        List<SysDictVO> dictList = new ArrayList<>(typeList.size());
        for (SysDictType type : typeList) {
            SysDictVO dict = new SysDictVO();
            dict.setDictType(type.getDictType());

            for (SysDictData data : dataList) {
                if (type.getId().equals(data.getDictTypeId())) {

                    if(data.getDictTypeId().equalsIgnoreCase("4")&&data.getDictValue().equalsIgnoreCase("0")){
                        if(SecurityUser.getUser().getUsername().equalsIgnoreCase(UserAdminEnum.ADMIN.getValue())){
                            dict.getDataList().add(new SysDictVO.DictData(data.getDictLabel(), data.getDictValue(), data.getLabelClass()));
                        }
                    }else if(data.getDictTypeId().equalsIgnoreCase("4")&&!data.getDictValue().equalsIgnoreCase("0")){
                        dict.getDataList().add(new SysDictVO.DictData(data.getDictLabel(), data.getDictValue(), data.getLabelClass()));
                    }else{
                        dict.getDataList().add(new SysDictVO.DictData(data.getDictLabel(), data.getDictValue(), data.getLabelClass()));
                    }

                }
            }

            // 数据来源动态SQL
            if (type.getDictSource() == DictSourceEnum.SQL.getValue()) {
                // 增加动态列表
                String sql = type.getDictSql();
                try {
                    dict.setDataList(sysDictDataMapper.getListForSql(sql));
                } catch (Exception e) {
                    log.error("增加动态字典异常: type=" + type, e);
                }
            }

            dictList.add(dict);
        }

        return dictList;
    }

    @Override
    public void afterPropertiesSet() {
        refreshTransCache();
    }

    public void refreshTransCache() {
        // 异步不阻塞主线程，不会 增加启动用时
        CompletableFuture.supplyAsync(() -> {
            // 获取所有的字典项数据
            List<SysDictData> dataList = sysDictDataMapper.selectList(new LambdaQueryWrapper<>());
            // 根据类型分组
            Map<String, List<SysDictData>> dictTypeDataMap = dataList.stream().collect(Collectors
                    .groupingBy(SysDictData::getDictTypeId));
            List<SysDictType> dictTypeEntities = super.list();
            for (SysDictType dictTypeEntity : dictTypeEntities) {
                if (dictTypeDataMap.containsKey(dictTypeEntity.getId())) {
                    dictionaryTransService.refreshCache(dictTypeEntity.getDictType(), dictTypeDataMap.get(dictTypeEntity.getId())
                            .stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel)));
                }
            }
            return null;
        });
    }
}
